use chrono::NaiveDate;
use eframe::egui::{self, CentralPanel, Visuals};
use egui_plotter::EguiBackend;
use plotters::{coord::ReverseCoordTranslate, prelude::*};
use polars::prelude::*;

mod setfont;
// 数据结构
#[derive(Debug, Clone)]
struct StockData {
    date: NaiveDate,
    open: f64,
    high: f64,
    low: f64,
    close: f64,
    _volume: i64,
}

// 指标计算
fn calculate_ma(data: &[StockData], window: usize) -> Vec<f64> {
    data.windows(window)
        .map(|w| w.iter().map(|d| d.close).sum::<f64>() / window as f64)
        .collect()
}

// GUI主应用
struct StockApp {
    data: Vec<(usize, StockData)>,
    //ma5: Vec<f64>,
    //ma20: Vec<f64>,
    candlecnt: usize,
    startcandleidx: usize,
}

impl StockApp {
    fn new(cc: &eframe::CreationContext<'_>) -> Self {
        // Disable feathering as it causes artifacts
        let context = &cc.egui_ctx;

        context.tessellation_options_mut(|tess_options| {
            tess_options.feathering = false;
        });
        setfont::setup_custom_fonts(&cc.egui_ctx);
        context.set_visuals(Visuals::light());
        // 加载示例数据
        /*let df = df!(
            "date" => [NaiveDate::from_ymd_opt(2024,8,1).unwrap(),NaiveDate::from_ymd_opt(2024,8,2).unwrap(),NaiveDate::from_ymd_opt(2024,8,3).unwrap(),NaiveDate::from_ymd_opt(2024,8,4).unwrap()],
            "open" => [50.0, 52.3, 48.7, 53.2],
            "high" => [57.9, 72.5, 53.6, 83.1],
            "low" => [1.56, 1.77, 1.65, 1.75],
            "close" => [50.1, 52.8, 48.8, 53.3],
            "volume" => [1000.0, 2000.0, 1500.0, 3000.0],
            )
            .unwrap();

        //println!("{}", df);
        let mut data = vec![];
        let rowcnt = df.height();
        let col1 = df["date"].date().unwrap();
        let col2 = df["open"].f64().unwrap();
        let col3 = df["high"].f64().unwrap();
        let col4 = df["low"].f64().unwrap();
        let col5 = df["close"].f64().unwrap();
        let col6 = df["volume"].f64().unwrap();*/
        let data = StockApp::collect_data();

        Self {
            data,
            //ma5,
            //ma20,
            candlecnt: 100,
            startcandleidx: 0,
        }
    }
    fn load_csv(file_path: &str) -> DataFrame {
        // 读取CSV文件
        let df_csv = CsvReadOptions::default()
            .with_infer_schema_length(None)
            .with_has_header(true)
            .with_parse_options(CsvParseOptions::default().with_try_parse_dates(true))
            .try_into_reader_with_file_path(Some(file_path.into()))
            .unwrap()
            .finish()
            .unwrap();
        //println!("{}",df_csv);
        df_csv
    }
    fn collect_data() -> Vec<(usize, StockData)> {
        let df = StockApp::load_csv("stock_data/000001.csv");
        let mut data = vec![];
        let rowcnt = df.height();
        let col1 = df["日期"].date().unwrap();
        let col2 = df["开盘"].f64().unwrap();
        let col3 = df["最高"].f64().unwrap();
        let col4 = df["最低"].f64().unwrap();
        let col5 = df["收盘"].f64().unwrap();
        let col6 = df["成交量"].i64().unwrap();

        for i in 0..rowcnt {
            let days = col1.get(i).unwrap();
            let basedate = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
            let date = basedate + chrono::Duration::days(days as i64);
            let open = col2.get(i).unwrap();
            let high = col3.get(i).unwrap();
            let low = col4.get(i).unwrap();
            let close = col5.get(i).unwrap();
            let volume = col6.get(i).unwrap();

            data.push((
                i,
                StockData {
                    date,
                    open,
                    high,
                    low,
                    close,
                    _volume: volume,
                },
            ));
        }
        data
    }
}

impl eframe::App for StockApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
            egui::menu::bar(ui, |ui| {
                ui.menu_button("文件", |ui| {
                    if ui.button("退出").clicked() {
                        ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
                    }
                });
            });
        });
        egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
            ui.label("指数");
        });
        egui::CentralPanel::default().show(ctx, |ui| {
            // 时间轴控制
            ui.vertical(|ui| {
                ui.horizontal(|ui| {
                    ui.label("显示k线数:");
                    ui.add(egui::Slider::new(&mut self.candlecnt, 28..=1000).text("k线数"));
                });

                ui.horizontal(|ui| {
                    ui.label("开始k线:");
                    ui.add(
                        egui::Slider::new(&mut self.startcandleidx, 0..=self.data.len() - 1)
                            .text("k线起始序号"),
                    );
                });
            });
            // 绘图区域
            CentralPanel::default().show_inside(ui, |ui| {
                ui.input(|input| {
                    if input.key_down(egui::Key::ArrowUp) {
                        self.candlecnt += 10;
                        self.candlecnt = self.candlecnt.clamp(28, 1000);
                    }
                    if input.key_down(egui::Key::ArrowDown) {
                        self.candlecnt -= 10;
                        self.candlecnt = self.candlecnt.clamp(28, 1000);
                    }
                });
                if self.data.len() > 0 {
                    let startidx = self.startcandleidx;
                    let endidx = self.startcandleidx + self.candlecnt;
                    let endidx = if endidx > self.data.len() {
                        self.data.len()
                    } else {
                        endidx
                    };
                    let current_data = &self.data[startidx..endidx];

                    let root = EguiBackend::new(ui).into_drawing_area();
                    root.fill(&BLUE).unwrap();

                    let minx = current_data[0].0 as f64 - 0.5;
                    let maxx = current_data.last().unwrap().0 as f64 + 0.5;
                    // 设置图表
                    let mut chart = ChartBuilder::on(&root)
                        //.margin(200)
                        .set_all_label_area_size(40)
                        .build_cartesian_2d(
                            minx..maxx,
                            current_data
                                .iter()
                                .map(|d| d.1.low)
                                .fold(f64::MAX, |acc, x| if x < acc { x } else { acc })
                                ..current_data.iter().map(|d| d.1.high).fold(0., |acc, x| {
                                    if x > acc {
                                        x
                                    } else {
                                        acc
                                    }
                                }),
                        )
                        .unwrap();

                    chart
                        .configure_mesh()
                        .light_line_style(&TRANSPARENT) //隐藏副网格线
                        .x_label_formatter(&|x| {
                            return self.data[*x as usize].1.date.format("%y-%m-%d").to_string();
                        })
                        .draw()
                        .unwrap();

                    // 绘制K线
                    chart
                        .draw_series(current_data.iter().map(|(idx, candle)| {
                            let x = *idx as f64;
                            let y_open = candle.open;
                            let y_close = candle.close;
                            let y_high = candle.high;
                            let y_low = candle.low;

                            let fill_color = if y_close > y_open {
                                RED
                            } else if y_close < y_open {
                                GREEN
                            } else {
                                BLACK
                            };
                            // 绘制垂直线（最高价到最低价）
                            let vertical_line = PathElement::new(
                                vec![(x, y_high), (x, y_low)],
                                ShapeStyle {
                                    color: fill_color.to_rgba(),
                                    filled: false,
                                    stroke_width: 1,
                                },
                            );
                            vertical_line
                        }))
                        .unwrap();

                    chart
                        .draw_series(current_data.iter().map(|(idx, candle)| {
                            let x = *idx as f64;
                            let y_open = candle.open;
                            let y_close = candle.close;
                            let _y_high = candle.high;
                            let _y_low = candle.low;
                            // 绘制矩形（开盘价到收盘价）
                            let fill_color = if y_close > y_open {
                                RED.filled()
                            } else if y_close < y_open {
                                GREEN.filled()
                            } else {
                                BLACK.into()
                            };
                            let rect =
                                Rectangle::new([(x - 0.4, y_open), (x + 0.4, y_close)], fill_color);
                            rect
                        }))
                        .unwrap();

                    // 处理鼠标悬停
                    if let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos()) {
                        //println!("{}", mouse_pos);
                        let mouse_pos = mouse_pos - ui.min_rect().min;
                        if let Some(logic_pos) = chart
                            .as_coord_spec()
                            .reverse_translate((mouse_pos.x as i32, mouse_pos.y as i32))
                        {
                            chart
                                .draw_series(PointSeries::of_element(
                                    [logic_pos],
                                    5,
                                    &RED,
                                    &|c, s, st| {
                                        return EmptyElement::at(c)
                                            + Circle::new((0, 0), s, st.filled())
                                            + Text::new(
                                                format!("{:?}", c),
                                                (10, 0),
                                                ("sans-serif", 10).into_font(),
                                            );
                                    },
                                ))
                                .unwrap();
                            let idx = (logic_pos.0 - 0.5) as usize;
                            if let Some(candle) = self.data.get(idx) {
                                let text = format!(
                                    "日期: {}\n开盘: {:.2}\n收盘: {:.2}\n最高: {:.2}\n最低: {:.2}",
                                    candle.1.date,
                                    candle.1.open,
                                    candle.1.close,
                                    candle.1.high,
                                    candle.1.low
                                );
                                egui::show_tooltip_text(
                                    ui.ctx(),
                                    ui.layer_id(),
                                    egui::Id::new("my_tooltip"),
                                    text,
                                );
                            }
                        }
                    }
                    // 绘制均线
                    /*chart
                        .draw_series(LineSeries::new(
                            current_data
                                .iter()
                                .zip(&self.ma5[..self.current_idx])
                                .map(|(d, &ma)| (d.date, ma)),
                            BLUE.stroke_width(2),
                        ))
                        .unwrap();

                    chart
                        .draw_series(LineSeries::new(
                            current_data
                                .iter()
                                .zip(&self.ma20[..self.current_idx])
                                .map(|(d, &ma)| (d.date, ma)),
                            YELLOW.stroke_width(2),
                        ))
                        .unwrap();*/
                }
            });
        });
    }
}

fn main() -> eframe::Result {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([1200.0, 800.0]),
        ..Default::default()
    };

    eframe::run_native(
        "股票复盘工具",
        options,
        Box::new(|cc| Ok(Box::new(StockApp::new(cc)))),
    )
}
